package cn.stimd.spring.context.support;

import cn.stimd.spring.beans.factory.config.BeanPostProcessor;
import cn.stimd.spring.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Stimd
 * 项目地址：https://gitee.com/stimd/spring-wheel
 * 公众号：Java编程探微
 */
public class PostProcessorRegistrationDelegate {

    public static void registerBeanPostProcessors(ConfigurableBeanFactory beanFactory) {
        List<String> beanNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class);
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();

        for (String ppName : beanNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(pp);
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessors.add(pp);
            }
            else {
                nonOrderedPostProcessors.add(pp);
            }
        }

        //先注册PriorityOrdered
        sortPostProcessors(priorityOrderedPostProcessors);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        //再注册Ordered
        sortPostProcessors(orderedPostProcessors);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        //注册普通的BeanProcessor
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    }


    private static void sortPostProcessors(List<?> postProcessors) {
        postProcessors.sort(OrderComparator.INSTANCE);
    }


    private static void registerBeanPostProcessors(
            ConfigurableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
        for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }
}
